/**
  *****************************************************************************
  * @file BAG302 热阴极真空计驱动
  * @brief 
  * @author Evan
  * @version V1.0.0
  * @date 2023/10/19
  *****************************************************************************
  */
 /* Includes -----------------------------------------------------------------*/
#include "dev_bag302.h"
#include "drv_f4_gpio.h"
#include "drv_f4_usart.h"
#include "drv_f4_delay_168MHz.h"
#include "system.h"
#include "device_table.h"
#include "FreeRTOS.h"
#include "task.h"
#include "func_DownMode.h"


/* Private defines ----------------------------------------------------------*/
#define USE_BAG302_DEBUG 1

/* Private Struct -----------------------------------------------------------*/

/* Private enum -------------------------------------------------------------*/

/* Private Variable ---------------------------------------------------------*/
//Pointer

//Array                  
uint8_t bag302_addr[2] = {0x30,0x31}; //BAG302地址 Upper nibble(Addr offset) Lower nibble(Addr)
uint8_t bag302_cmd = BAGREAD_PRE; //BAGREAD_SW; //BAGREAD_PRE;
uint8_t bag302_en = 0;
//Const
bag302val_t bag302val;

/* Private function prototypes ----------------------------------------------*/
//USART3用做485（目前没有232外设），目前接一个传感器，通过地址识别
#if 1
drv_gpio_t com_wr = //485读写选择
{
    .PIN = "A15", //"D3",
    .MODE = OUTPUT_DOWN,
    .INIT_LEVEL = LOW_LEVEL,
};

drv_usart_t bag302_com = //BAG302压力传感器串口
{
    .Drv_Num = "USART3", //"UART5",
    .Tx_Pin = "C10" ,//"C12",
    .Rx_Pin = "C11", //"D2",
    .BaudRate = 19200, //19200,
    .WordLength = USART_WORDLENGTH_8BIT,
    .StopBits = USART_STOPBITS_1BIT,
    .Parity = USART_PARITY_NO,
    .Idle_CallBack = BAG302ComCallBack,
    .Rx_Priority = 5,
};

#else

drv_gpio_t com_wr = //485读写选择
{
    .PIN = "D3",
    .MODE = OUTPUT_DOWN,
    .INIT_LEVEL = LOW_LEVEL,
};

drv_usart_t bag302_com = //BAG302压力传感器串口
{
    .Drv_Num = "UART5",
    .Tx_Pin = "C12",
    .Rx_Pin = "D2",
    .BaudRate = 119200,
    .WordLength = USART_WORDLENGTH_8BIT,
    .StopBits = USART_STOPBITS_1BIT,
    .Parity = USART_PARITY_NO,
    .Idle_CallBack = BAG302ComCallBack,
    .Rx_Priority = 5,
};
#endif



func_DownMode_t bag302_fun = //bag302压力传感器下行设备管理
{
    .outTime = 20,    //超时时间
    .SendCnt = 0,       //重发次数
    .IdleDelay = 200,   //总线空闲时间
    .send_data = BAG302Com_send_data,
};


#if USE_BAG302_DEBUG
 uint8_t bag302_tx_buf_db[64];
static uint8_t bag302_tx_len_db = 0;
 uint8_t bag302_rx_buf_db[64];
static uint8_t bag302_rx_len_db = 0;
#endif

/*****************************************************************************
* @brief bag302 发送接口函数
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
uint32_t BAG302Com_send_data(uint8_t *data, uint32_t len)
{
	#if 1
	uint32_t retry = 0;
    com_wr.Write(&com_wr, 1);
    bag302_com.Write(&bag302_com, data, len);
	
	//bag302_com.private.USARTx, 
		
	while( (RESET == USART_GetFlagStatus(USART3, USART_FLAG_TC) ) && (++retry < 0x7FFFFFFF) );
	USART_ClearFlag(USART3, USART_FLAG_TC);
	
	//vTaskDelay(pdMS_TO_TICKS(2));
	
    com_wr.Write(&com_wr, 0);
	return 0;
	#else

    com_wr.Write(&com_wr, 1);

	
	vTaskDelay(pdMS_TO_TICKS(2000));
	
    com_wr.Write(&com_wr, 0);
	
	#endif
}

/*****************************************************************************
* @brief  bag302 485串口接收回调函数
* ex:     All Responses are 13 characters long.
* @par 
* None
* @retval 
*****************************************************************************/
uint8_t err_num = 0;
static void BAG302ComCallBack(uint8_t *data, uint32_t len)
{
	bag302_fun.read_callback(&bag302_fun, data, len);
	
#if USE_BAG302_DEBUG	
	memcpy(bag302_rx_buf_db, data, len);
	
	if(bag302_rx_buf_db[0] != 0x2A){
		++err_num;
	}
#endif
}

/*****************************************************************************
* @brief  获取BAG302压力传感器处理的工作任务状态
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
static DOWN_TASK_STATE bag302_task_st(void *fun)
{
    if (fun == NULL)
        return Task_IsOver;
    else
        return Task_IsOk;
}

/*****************************************************************************
* @brief  BAG302压力传感器任务接收数据处理
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
static int32_t bag302_task_recv(void *fun, uint8_t *pBuf, int32_t len)
{
    if (fun == NULL)
        return -1;

    if (pBuf == NULL)
    {
        bag302val.status = 0;
		
        return 0;
    }
    else
        bag302val.status = 1;  

    BAG302MastDecode(pBuf, len, 0);
	
//    pressuresensor_log_print("RX:", (char *)pBuf, (int)len);
    return 0;
}

void dev_bag302_test_send(void)
{
	uint8_t buf[64];
	uint8_t len = 0;
	
	len = BAG302AssembleSendCom(bag302_addr, buf);
	
#if USE_BAG302_DEBUG	
	memcpy(bag302_tx_buf_db, buf, len);
#endif 
	BAG302Com_send_data(buf, len);
}


/*****************************************************************************
* @brief  BAG302压力传感器任务发送数据处理
* ex:
* @par 
* None
* @retval 
*****************************************************************************/
static int32_t bag302_task_send(void *fun, uint8_t *pBuf)
{
    int32_t res;
    if (fun == NULL || pBuf == NULL)
        return -1;

      res = BAG302AssembleSendCom(bag302_addr,pBuf);
	
#if USE_BAG302_DEBUG	
	memcpy(bag302_tx_buf_db, pBuf, 6);
#endif 
    
//    pressuresensor_log_print("TX:", (char *)pBuf, (int)res);
    return res;
}

/*******************************************************************************
 * @brief    BAG302组装发送命令
 *
 * @param
 * @param
 * @param
 * @param
 *
 * @return
*******************************************************************************/
int BAG302AssembleSendCom(uint8_t *addr,uint8_t *p_dst)
{
    uint16_t len = 0;
    if(p_dst == NULL)
        return -1;
    
    p_dst[len++] = 0x23;//#
    p_dst[len++] = addr[0];//设备地址
    p_dst[len++] = addr[1];
    switch(bag302_cmd)
    {
        case BAGREAD_PRE:
            p_dst[len++] = 0x52;//R
            p_dst[len++] = 0x44;//D
            break;
        
        case BAGTURN_IG:
            p_dst[len++] = 0x49;//I
            p_dst[len++] = 0x47;//G
            if(bag302_en == 0)
                p_dst[len++] = 0x30;//0-关闭
            else if(bag302_en == 1)
                p_dst[len++] = 0x31;//1-打开
            break;
            
        case BAGREAD_IGONOFF:
            p_dst[len++] = 0x49;//I
            p_dst[len++] = 0x47;//G
            p_dst[len++] = 0x53;//S
            break;
                
        case BAGREAD_IGMODULE:
            p_dst[len++] = 0x52;//R
            p_dst[len++] = 0x53;//S
            break;
            
        case BAGREAD_SW:
            p_dst[len++] = 0x56;//V
            p_dst[len++] = 0x45;//E
            p_dst[len++] = 0x52;//R
            break;
        
        case BAG_RST:
            p_dst[len++] = 0x52;//R
            p_dst[len++] = 0x53;//S
            p_dst[len++] = 0x54;//T
            break;
        
        default:
            return -2;
     }       
        
    p_dst[len++] = 0x0D;//回车
    
    return len;
}



/*******************************************************************************
 * @brief    接收命令解析
 *
* @param    p_data:接收的数据
 * @param   len：接收数据长度
 * @param
 * @param
 *
 * @return
*******************************************************************************/
int BAG302MastDecode(uint8_t *p_data, uint8_t len, uint16_t offset)
{
    char val[9] = {0,0,0,0,0,0,0,0,'\0'};
	float real = 0; 
	float exp = 0;
	
	char* addr = NULL;
	
    if((p_data[0] == 0x2A) && (p_data[1] == bag302_addr[0]) 
        && (p_data[2] == bag302_addr[1]) && (p_data[3] == 0x20) && (p_data[len-1] == 0x0D))
    {
        switch(bag302_cmd)
        {
            case BAGREAD_PRE:
                if(len == 13)
                {
                    memcpy(val,&p_data[4],8);
					addr = strstr((char*)val,"E");
					if(addr == NULL)
					{
						return -2;
					}else{
					*addr = '\0';	
					real = atof((char*)val);
					exp = atof(addr+1);
						
					if(strstr((char*)addr+1,"+") != NULL){
						bag302val.P_sensor = pow(real, exp);//压力值转为浮点数存储
					}else{
						bag302val.P_sensor = pow(real, -exp);//压力值转为浮点数存储
					}
				}
						
					
                }
                else
                    return -2;
            break;
                
            case BAGTURN_IG:
                if((len == 13) && (p_data[len-3] == 0x4F) && (p_data[len-2] == 0x4B))//若回复为OK
                {
                    bag302_cmd =  BAGREAD_IGONOFF;//将下条命令改为读取IG ON/OFF状态
                }
                else
                    return -3;
            break;
                
            case BAGREAD_IGONOFF:
                if((len == 13) || (len == 12))
                {
                    if(p_data[4] == bag302_en)//回复IG开关状态与设置开关状态相同
                    {
                        bag302_cmd =  BAGREAD_PRE;//将下条命令改为读取压力
                    }
                    else//若不同
                    {
//                        times++;//重发次数
                        bag302_cmd =  BAGTURN_IG;//再次发送IG开关命令
                    }
                    
                }
                else
                    return -4;
                    
            break;
                
            case BAGREAD_IGMODULE:
                 if((p_data[4] == 0x30) && (p_data[5] == 0x30))
                     bag302val.igsta = IG_ST_OK;
                 else if((p_data[4] == 0x30) && (p_data[5] == 0x31))
                     bag302val.igsta = IG_OVPRS;
                 else if((p_data[4] == 0x30) && (p_data[5] == 0x32))
                     bag302val.igsta = IG_EMISS;
                 else if((p_data[4] == 0x30) && (p_data[5] == 0x38))
                     bag302val.igsta = IG_POWER;
                 else if((p_data[4] == 0x32) && (p_data[5] == 0x30))
                     bag302val.igsta = IG_ION_C;
                 else
                     return -5;
                 bag302_cmd =  BAGREAD_PRE;//将下条命令改为读取压力
                     
            break;
                
            case BAGREAD_SW:
                if(len == 12)
                {
                    bag302_cmd =  BAGREAD_PRE;//将下条命令改为读取压力
                }
                else
                    return -4;
            break;
                
            case BAG_RST:
//                if((p_data[len-3] == 0x4F) && (p_data[len-2] == 0x4B))//若回复为OK
//                {
                    bag302_cmd =  BAGREAD_PRE;//将下条命令改为读取压力
//                }
//                else
//                    return -5;
            break;

            default:
                return -6;
        }
        
        return 0;

    }
    else
        return -1;

}

/***********************************************************************************
 * @brief 压力传感器初始化		
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
void BAG302_init(void)
{
    if (Drv_Gpio_Init(&com_wr) < 0)
    {
        return;
    }

    if (Drv_Usart_Init(&bag302_com) < 0)
    {
        while (1); 
    }

    if (Func_DownMode_Init(&bag302_fun) < 0)
    {
        while (1); 
    }

//	set_modbus_page(&ps_page, P_sensor_num);
//    //set_modbus_page(&ps_page[0], P_sensor_num);  //AB串口共用一个表
	
    bag302_fun.CommTaskApply(&bag302_fun, ComType_Cycle, bag302_task_st,
                          bag302_task_send, bag302_task_recv);
}

/***********************************************************************************
 * @brief 压力传感器轮训函数	
 * ex:
 * @par
 * None
 * @retval void None
 **********************************************************************************/
void BAG302_handler(uint16_t timebase)
{
    bag302_fun.DownMode_task(&bag302_fun, timebase);
	
	//SoftDelay_ms(100);
	//将压力缓存提供接口可读多个值
}
